import {
  type AigcModel,
  baiduAuth,
  delImg,
  getIcpImgList,
  getImg,
  getModelList,
  saveImg,
  txtToImg,
} from '@/api/api-manage/aigc'
import { getToken } from '@/utils/auth'
import { message } from '@/utils/message'
import time from '@/utils/time'
import axios from 'axios'
import type { UploadInstance, UploadProps, UploadUserFile } from 'element-plus'
import { ElLoading, ElMessage, ElMessageBox } from 'element-plus'
import FileSaver from 'file-saver'
import Cookies from 'js-cookie'
import JSZip from 'jszip'
import { cloneDeep } from 'lodash-es'
import { computed, onMounted, reactive, ref } from 'vue'

export default function useTextToImageGeneration() {
  const uploadRef = ref<UploadInstance>(null!)
  // 预览地址
  const dialogImageUrl = ref('')
  const previewDialogVisible = ref(false)
  const fileList = ref<UploadUserFile[]>([])

  // 文本内容
  const formData = ref({
    prompt: '',
    modelName: null,
  })
  const currentImgRequestId = ref('0')

  // 模型选择
  const modelOptions = ref<Array<AigcModel>>([])

  // 影响比重参数
  const impactWeightImageUrl = ref('')
  const impactWeight = ref(1)
  const showImageMask = ref(false)

  const uploadMaterialDialogVisible = ref(false)
  const materialUploadTab = ref('local')

  const authToken = getToken()

  const uploadUrl = import.meta.env.VITE_API_PREFIX + '/resource/oss/upload'

  // 风格选择
  const imageStyle = ref('')

  // 生成图片张数
  const generatePictureNumber = ref(1)

  // 尺寸选择
  const sizeStyle = ref(1)
  const size = ref('512*512')

  // 生成风格
  const genStyleOptions = reactive([
    {
      src: '/src/assets/creativity/chinese-style2.jpg',
      checked: false,
    },
    {
      src: '/src/assets/creativity/chinese-style2.jpg',
      checked: false,
    },
    {
      src: '/src/assets/creativity/chinese-style2.jpg',
      checked: false,
    },
    {
      src: '/src/assets/creativity/chinese-style2.jpg',
      checked: false,
    },
    {
      src: '/src/assets/creativity/chinese-style2.jpg',
      checked: false,
    },
    {
      src: '/src/assets/creativity/chinese-style2.jpg',
      checked: false,
    },
  ])

  // 预览组别
  const previewGenerateIndex = ref(0)
  // 生成图片
  const generatedImages = ref([])
  // 待保存的图片列表
  const savingImages = ref([])
  // 图片总数
  const imageTotal = computed(() =>
    generatedImages.value.reduce((acc, item) => acc + item.imgList.length, 0)
  )

  const genRatioOptions = [
    {
      label: '适合头像1：1',
      value: 1,
    },
    {
      label: '适合海报9：16',
      value: 2,
    },
    {
      label: '适合电脑壁纸16：9',
      value: 3,
    },
  ]

  const genSizeOptionSet = [
    [],
    [
      {
        label: '512*512',
        value: '512*512',
      },
      {
        label: '1024*1024',
        value: '1024*1024',
      },
      // {
      //   label: '2048*2048',
      //   value: '2048*2048',
      // },
    ],
    [
      {
        label: '360*640',
        value: '360*640',
      },
      {
        label: '720*1280',
        value: '720*1280',
      },
      // {
      //   label: '1440*2560',
      //   value: '1440*2560',
      // },
    ],
    [
      {
        label: '640*360',
        value: '640*360',
      },
      {
        label: '1280*720',
        value: '1280*720',
      },
      // {
      //   label: '2560*1440',
      //   value: '2560*1440',
      // },
    ],
  ]
  const genSizeOptions = reactive([
    {
      label: '512*512',
      value: '512*512',
    },
    {
      label: '1024*1024',
      value: '1024*1024',
    },
    // {
    //   label: '2048*2048',
    //   value: '2048*2048',
    // },
  ])

  const handleSizeStyleChange = (e) => {
    genSizeOptions.splice(0, 3, ...genSizeOptionSet[e])
    size.value = genSizeOptionSet[e][0].value
  }

  const handleImageStyle = (e) => {
    console.log(e)
    imageStyle.value = e
  }

  /**
   * 一键生成
   * @returns
   */
  async function handleGenerate() {
    const styleText = imageStyle.value == '' ? '' : ',' + imageStyle.value
    const sizeArray = size.value.split('*')
    const params = {
      prompt: formData.value.prompt + styleText,
      modelName: formData.value.modelName,
      width: parseInt(sizeArray[0]),
      height: parseInt(sizeArray[1]),
      image_num: generatePictureNumber.value,
      image: impactWeightImageUrl.value, // 参考图
      change_degree: impactWeight.value,
    }

    const loading = ElLoading.service({
      lock: true,
      text: '图片生成中...',
    })
    try {
      const { data } = await txtToImg(params)
      if (data) {
        await pollImagesFromTaskId(formData.value.modelName, data)
      } else {
        await baiduAuth()
        ElMessage.warning('生成失败，请重新点击一键生成按钮')
      }
    } finally {
      loading.close()
    }
  }

  async function pollImagesFromTaskId(modelName: string, taskId: string) {
    const MAX_RETRY_COUNT = Infinity
    const RETRY_INTERVAL = 5 * time.Second

    let retryCount = -1
    async function pollFn() {
      retryCount++
      if (retryCount >= MAX_RETRY_COUNT) {
        throw new Error('已达到最大重试次数，获取图片数据失败')
      }

      const { data } = await getImg(modelName, taskId)
      if (!data) {
        throw new Error('获取图片数据失败')
      }

      const { taskStatus, imgList } = data
      if (taskStatus === 'SUCCESS') {
        return imgList
      }
      if (taskStatus === 'FAILED') {
        throw new Error('获取图片数据失败')
      }
      await time.sleep(RETRY_INTERVAL)
      return await pollFn()
    }

    const result = await pollFn().catch((err: Error) => {
      message(`文本内容暂时无法生成图片: ${err.message}`, { type: 'error' })
    })
    if (!result) {
      return
    }

    previewGenerateIndex.value = 0

    const imgList = result
      .filter((v) => v.imgApproveConclusion === 'pass')
      .map((v) => ({
        url: v.imgUrl,
      }))
    const saveImgObj = {
      taskId: taskId,
      imgUrl: cloneDeep(imgList),
    }
    const showObj = {
      taskId: taskId,
      imgList: cloneDeep(imgList),
    }
    // 需要保存的图片列表
    savingImages.value.push(saveImgObj)
    generatedImages.value.unshift(showObj)
    currentImgRequestId.value = ''
  }

  // 保存所有
  function saveAll() {
    const data = {
      imgBoList: savingImages.value,
    }
    saveImg(data).then((res) => {
      if (res.code == 200) {
        ElMessage.success('保存成功')
        savingImages.value = []
        generatedImages.value = []
        getHistoryImages()
      } else {
        ElMessage.error(res.msg)
      }
    })
  }

  function showDialog() {
    uploadMaterialDialogVisible.value = true
  }

  // 选择素材
  function handleCheckedPic(item, index) {
    for (let i = 0; i < genStyleOptions.length; i++) {
      genStyleOptions[i].checked = false
    }
    genStyleOptions[index].checked = !genStyleOptions[index].checked
  }

  // 删除已上传图片
  const handleRemove: UploadProps['onRemove'] = () => {
    uploadRef.value.clearFiles()
    impactWeightImageUrl.value = ''
  }

  // 预览图片
  const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
    dialogImageUrl.value = uploadFile.url!
    previewDialogVisible.value = true
  }

  const beforeUpload: UploadProps['beforeUpload'] = (rawFile) => {
    if (rawFile.type !== 'image/jpeg' && rawFile.type !== 'image/png') {
      ElMessage.error('只支持JPG、PNG格式的图片!')
      return false
    } else if (rawFile.size / 1024 / 1024 > 7) {
      ElMessage.error('图片不能超过7MB!')
      return false
    }
    return true
  }

  // 上传成功
  const handleSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {
    dialogImageUrl.value = URL.createObjectURL(uploadFile.raw!)
    impactWeightImageUrl.value = response.data.url
  }

  const handleClose = () => {
    for (let i = 0; i < genStyleOptions.length; i++) {
      genStyleOptions[i].checked = false
    }

    uploadRef.value.clearFiles()
    uploadMaterialDialogVisible.value = false
  }

  const handleConfirm = () => {
    uploadMaterialDialogVisible.value = false
  }

  const handleClickTask = (index, item) => {
    currentImgRequestId.value = item.requestId
    previewGenerateIndex.value = index
  }

  const handleDeleteImageWeight = () => {
    impactWeight.value = 1
    impactWeightImageUrl.value = ''
  }

  const handleMoveEnter = () => {
    showImageMask.value = true
  }

  const handleMoveOut = () => {
    showImageMask.value = false
  }

  // 获取百度aitoken
  async function getBdAiToken() {
    const { data } = await baiduAuth()
    Cookies.set('baiduAiToken', data.access_token)
  }

  /**
   * 删除图片
   * @param row
   */

  const handleDeleteImg = (row) => {
    if (generatedImages.value.length > 0) {
      ElMessageBox.confirm('是否确认删除该图片？')
        .then(function () {})
        .then(() => {
          if (!currentImgRequestId.value) {
            if (generatedImages.value.length > 0) {
              const taskId = generatedImages.value[previewGenerateIndex.value].taskId
              generatedImages.value.splice(previewGenerateIndex.value, 1)
              savingImages.value = savingImages.value.filter((item) => item.taskId !== taskId)
              previewGenerateIndex.value = 0
              handleClickTask(
                previewGenerateIndex.value,
                generatedImages.value[previewGenerateIndex.value]
              )
            }
          } else {
            const loading = ElLoading.service({
              lock: true,
              text: '正在删除...',
            })
            delImg(currentImgRequestId.value)
              .then((res) => {
                if (res.code === 200) {
                  // previewGenerateIndex.value = 0;
                  // initImgList();
                  if (generatedImages.value.length > 0) {
                    generatedImages.value.splice(previewGenerateIndex.value, 1)
                    previewGenerateIndex.value = 0
                    handleClickTask(
                      previewGenerateIndex.value,
                      generatedImages.value[previewGenerateIndex.value]
                    )
                  }
                  ElMessage.success('删除成功')
                } else {
                  ElMessage.error(res.msg)
                }
              })
              .finally(() => {
                loading.close()
              })
          }
        })
    } else {
      ElMessage.error('图片列表为空，删除失败！')
    }
  }

  async function downloadAllImages() {
    let arr = [] //将图片地址存入该数组y
    const loading = ElLoading.service({
      lock: true,
      text: '图片下载中...',
    })
    generatedImages.value.forEach((element) => {
      // 获取到的所有图片
      if (element.imgList.length > 0) {
        element.imgList.forEach((item) => {
          arr.push(item.url)
        })
      }
    })
    batchDownloadImages(arr).finally(() => {
      loading.close()
    })
  }

  // 批量下载
  function batchDownloadImages(selectImgList) {
    const zip = new JSZip()
    const cache = {}
    const promises = []
    selectImgList.forEach((item) => {
      const promise = getFile(item).then((data) => {
        // 下载图片, 并存成ArrayBuffer对象
        const arr_name = item.split('/')
        let file_name = arr_name[arr_name.length - 1] // 获取图片名

        zip.file(file_name, data, {
          binary: true,
        }) // 逐个添加图片
        cache[file_name] = data
      })
      promises.push(promise)
    })
    return Promise.all(promises).then(() => {
      zip
        .generateAsync({
          type: 'blob',
        })
        .then((content) => {
          // 生成二进制流
          FileSaver.saveAs(content, '图片.zip') // 利用file-saver保存图片
        })
    })
  }

  // 下载图片
  function getFile(url) {
    return new Promise((resolve, reject) => {
      axios({
        method: 'get',
        url,
        responseType: 'arraybuffer',
      })
        .then((data) => {
          resolve(data.data)
        })
        .catch((error) => {
          reject(error.toString())
        })
    })
  }

  /**
   * 获取历史生成图片
   */
  function getHistoryImages() {
    getIcpImgList().then((res) => {
      if (res.code == 200) {
        generatedImages.value = res.data
        currentImgRequestId.value = generatedImages.value[0].requestId
      }
    })
  }

  async function getModelOptions() {
    const { data } = await getModelList()
    modelOptions.value = data
  }

  onMounted(async () => {
    const bdAiToken = Cookies.get('baiduAiToken')
    if (!bdAiToken) {
      await getBdAiToken()
    }
  })

  getModelOptions()

  return {
    formData,
    modelOptions,
    materialUploadTab,
    authToken,
    dialogImageUrl,
    uploadMaterialDialogVisible,
    fileList,
    generatedImages,
    generatePictureNumber,
    genRatioOptions,
    genSizeOptions,
    genStyleOptions,
    imageStyle,
    imageTotal,
    impactWeight,
    impactWeightImageUrl,
    previewDialogVisible,
    previewGenerateIndex,
    showImageMask,
    size,
    sizeStyle,
    savingImages,
    uploadRef,
    uploadUrl,
    beforeUpload,
    downloadAllImages,
    handleCheckedPic,
    handleClickTask,
    handleClose,
    handleConfirm,
    handleDeleteImg,
    handleDeleteImageWeight,
    handleGenerate,
    handleImageStyle,
    handleMoveEnter,
    handleMoveOut,
    handlePictureCardPreview,
    handleRemove,
    handleSizeStyleChange,
    handleSuccess,
    saveAll,
    showDialog,
  }
}
